package main.pmc;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import com.alibaba.fastjson.JSONArray;
import lombok.SneakyThrows;
import org.apache.http.impl.client.BasicCookieStore;
import utils.SmallTool;
import utils.StringUtil;
import utils.httpclient.HttpClient;
import utils.httpclient.HttpClientConfig;
import utils.httpclient.HttpClientUtil;

import java.io.IOException;
import java.net.URL;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.*;

import static main.pmc.LocalPmcFileCheck.isCheckDownType;
import static main.pmc.LocalPmcFileCheck2.getFileSize;
import static utils.StringUtil.delPointStr;

/**
 * @Author: 葛成瑞
 * @Date: 2025/2/12 15:20
 */
public class DownPmcFile {
    @SneakyThrows
    public static void main(String[] args) {
        // 下载pmc文件

//        String rootPath = "D:\\pmpmcdownfolder\\";
        String rootPath = "F:\\pmcdownextra\\";

//        String rootPath = "D:\\pmcdown\\";

        Db useTaiyi = Db.use();
        String saveTable = "pmcdown_new2";
        String allDate = "select max(pmid) as pmid  from " + saveTable;
        Entity query = useTaiyi.query(allDate).get(0);
        SmallTool.printMess("最大的id 是" + query.getStr("pmid"));
        Integer count = query.getInt("pmid");
        int breakSize = 100000;
        int pageSize = count / breakSize + 1;
        SmallTool.printMess("全部页码+++++++++" + pageSize);
        SmallTool.printMess("即将开始请提前关闭如果想的话");
        List<String> ipList = Ip.getAllIp();
        SmallTool.SleepMillis(5000L);
        SmallTool.printMess("任务开始+++++++++++++++++++++++++++++++++++++++++++++++++++++");
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                6,
                30,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(), new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 1; i <= pageSize; i++) {
            int start = breakSize * (i - 1) + 1;
            int end = i * breakSize;
            SmallTool.printMess("当前页码+++++" + i);
            SmallTool.printMess("开始id++" + start + "+++结束id++++" + end);
//            String paramSql = "select pmid,supp,down,path from " + saveTable + " where del = 1 and  pmid between  " + start + " and " + end;
            String paramSql = "select pmid,supp,down,path from " + saveTable + " where del = 1 and  pmid = 19820169 ";
//            String paramSql = "select pmid,supp,down,path from " + saveTable + " where down = 4 and  pmid between  " + start + " and " + end;

            Db useTaiyiSin = Db.use();
            List<Entity> querys = useTaiyiSin.query(paramSql);
//            List<Entity> querys = new ArrayList<>();

            //多綫程下载429 单线程下载
            querys.forEach(entity -> executor.submit(() -> {
                URL path = StringUtil.class.getClassLoader().getResource("useragent.txt");
                List<String> userList = FileUtil.readLines(path, "utf-8");
                Integer pmid = entity.getInt("pmid");
                String secondPath = "/" + pmid / 50000 + 1 + "/";
                String supp = entity.getStr("supp");
                Random random = new Random();
                int n = random.nextInt(userList.size());
                String userAgent = userList.get(n);
                String userIp;
                if (ipList.size() > 0) {
                    n = random.nextInt(ipList.size());
                     userIp = ipList.get(n);
                } else {
                    userIp = "";
                }

//                SmallTool.printMess("使用ip+" + userIp);
//                SmallTool.printMess("使用+userAgent+" + userAgent);
                if (StringUtil.isNotNull(pmid) && StringUtil.isNotNull(supp)) {
                    List<SaveEntity> strings = JSONArray.parseArray(supp, SaveEntity.class);
                    Map<String, SaveEntity> map = new HashMap<>();
                    Map<String, Integer> UrlCode = new HashMap<>();
                    for (SaveEntity string : strings) {
                        map.put(string.getUrl(), string);
                    }
                    Set<Integer> allResCode = new HashSet<>();
                    strings.forEach(s -> {
                        if (isCheckDownType(s.getUrl())) {
                            // 第一次都是null
                            if (s.getCode() != null && s.code.intValue() != 200) {
                                return;
                            }


//                            HttpClientConfig config = HttpClientUtil.getSearConfig(s);
                            HttpClientConfig config = HttpClientUtil.getSearConfig(s.getUrl(), "", userIp, userAgent, "", true);
                            config.setDirPath(rootPath + secondPath + pmid + "\\");
                            config.setTIME_OUT(230000);
                            config.setFilePath(getFileName(s.getUrl()));
                            config.setProxy(false);
                            if (StringUtil.isNotNull(s.getSize())) {
                                config.setFileByteSize(getFileSize(null, s.getSize()));
                            }
                            Integer downImageCode = 404;
                            try {
                                 downImageCode = HttpClient.getDownImageCode(config);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                            try {
                                if (downImageCode != null) {
                                    UrlCode.put(s.getUrl(), downImageCode);
                                    allResCode.add(downImageCode);
                                }else {
                                    System.out.println("downImageCode is null ");
                                }

                            }catch (Exception e){

                            }
                        }

                    });
                    // 跑完全部后 进行判断
                    // 全部都是200 则进行标记
                    List<SaveEntity> res = new ArrayList<>();
                    for (Map.Entry<String, SaveEntity> stringIntegerEntry : map.entrySet()) {
                        SaveEntity value = stringIntegerEntry.getValue();
                        SaveEntity saveEntity = new SaveEntity();
                        BeanUtil.copyProperties(value, saveEntity);
                        Integer code = UrlCode.get(stringIntegerEntry.getKey());
                        if (code != null) {
                            saveEntity.setCode(code);
                            res.add(saveEntity);
                        } else {
                            // 不能设置成200  否则会被认为是已经下载的 会进行校验 所有不是404 或者403的 非200 的都给默认404
                            if (saveEntity.getCode() != null && saveEntity.getCode() != 200&&saveEntity.getCode()!=429) {
                                saveEntity.setCode(404);
                            }else {
                                saveEntity.setCode(null);
                            }

                            res.add(saveEntity);
                        }
                    }
                    String s = JSONArray.toJSONString(res);
                    entity.set("supp", s);
                    entity.set("is_check", 2);
                    // 只要检验了旧需要下载检查
                    if (allResCode.size() == 1) {
                        ArrayList<Integer> integers = new ArrayList<>(allResCode);
                        Integer i1 = integers.get(0);
                        if (i1.intValue() == 200) {
                            entity.set("down", 2);
                            entity.set("del", 2);
                            entity.set("path", rootPath + secondPath + pmid + "\\");
                        } else {
                            if (i1 == 404 || i1 == 403) {
                                entity.set("down", 2);
                                entity.set("del", 2);
                            }else {
                                entity.set("del", 1);
                                entity.set("down", 4);
                            }

                        }
                    } else {
                        entity.set("del", 1);
                        entity.set("down", 2);
                    }
                    try {
                        Db use = Db.use();
                        use.insertOrUpdate(entity, "pmid");
                    } catch (SQLException e) {
                        throw new RuntimeException(e);
                    }
                }
            }));

        }
        executor.shutdown();
        while (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
            int activeCount = executor.getActiveCount();
            System.out.println("当前线程数" + activeCount);
            System.out.println("队列全部大小+"+executor.getTaskCount());
            long completedTaskCount = executor.getCompletedTaskCount();
            System.out.println("已完成任务数" + completedTaskCount);
        }
        long completedTaskCount = executor.getCompletedTaskCount();
        SmallTool.printMess("任务结束本批次结束size +"+completedTaskCount);


    }



    //判断存在?
    public static String getFileName(String url) {
        String filePath = url.split("/")[url.split("/").length - 1];
        filePath = delPointStr(filePath);
        return filePath;
    }


}
